package org.unikn.dbvis.tools;

import java.util.ArrayList;
import java.util.HashMap;

import org.unikn.dbvis.gui.GuiControlsOverlay;
import org.unikn.dbvis.net.BaseXConnection;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.XMLReaderFactory;

import processing.core.PApplet;
import controlP5.ControlEvent;


public class TestSketch extends PApplet {
	
	private static final long serialVersionUID = 1L;
	WorldMap wmap;
	BaseXConnection bxc;
	String result;
	private HashMap<String, MapPoint> map;
	private final GuiControlsOverlay guiControls = new GuiControlsOverlay();
	public int ellipseSize = 10;
	
	
	int day = 0;
	int zoom = 5;
	private int[][] col = new int[3][3];
//	private Random r = new Random();
	private boolean init = true;
	private HashMap<String, MapPoint> amap;
	private String filter ="";
	
		@Override
	public void setup() {
		int x = 1024;
		int y = 768;
		smooth();
		size(x, y);
	  frameRate(25);

		final int[][] tmp = { {153,201,8,100}, // pale green
				{155,5,5,100}, // pale red
		{70,180,193,100} // neutral
		
		};
		col = tmp;
		guiControls.setP(this);
		ellipseMode(CENTER);
//		smooth();
		background(51);
		wmap = new WorldMap(this, x, y);
		wmap.drawBackground(zoom);

		result = query();
		try {
			extract();
		} catch (Exception e) {
			e.printStackTrace();
		}

		
		this.map = createMap();
		drawNews();

	}

	private HashMap<String,MapPoint> createMap()
	{
		HashMap<String,MapPoint> map = new HashMap<String, MapPoint>();
		amap = new HashMap<String, MapPoint>();
		int i=0;
		final int j = GetLocations.longitude.size();
		for(  i =0; i< j;i++ ){
			float lat = GetLocations.latitude.get(i);
			float lon = GetLocations.longitude.get(i);
			String day = GetLocations.date.get(i);
			Point p = wmap.getPoint(lat, lon, zoom);
	// random key: check for right placing
			// final String key = " *"+ r.nextInt(90000);
			final String key = day + p.x + " " + p.y;
			if( null == map.get(key)){
				map.put(key, new MapPoint((int)p.x,(int)p.y, i ) ) ;
			}else{
				MapPoint mp = map.get(key);
				mp.add(i);
				map.put(key, mp);
			}
			final String key2 =  p.x + " " + p.y;
			
			if( null == amap.get(key2)){
				amap.put(key2, new MapPoint((int)p.x,(int)p.y, i ) ) ;
			}else{
				MapPoint mp = amap.get(key2);
				mp.add(i);
				amap.put(key2, mp);
			}
			
		} 

		return map;
	}
	@Override
	public void draw() {
		if (mousePressed || this.init || keyPressed ) {
			background(51);
			wmap.drawBackground(zoom);
			drawNews();
			this.init = false;
		}
		
	}

	private void drawNews() {
		int x, y, tonality, size;
		int cnt=0;
		stroke(0);
		MapPoint mp = null;
		HashMap<String, MapPoint>placemap = this.day==15 ? this.amap : this.map;
		ArrayList<Integer> filterText = new ArrayList<Integer>();
		if(this.filter !=""  )
		{
			filterText =  GetLocations.getCatByName(this.filter);
			guiControls.filterField.setLabel("Filter "+this.filter);
			if(filterText.isEmpty())
			{
				guiControls.filterField.setLabel("No Results for \""+this.filter+"\"");
				return;
			}
		}else
			guiControls.filterField.setLabel("Filter");
		
		for (String xy : placemap.keySet()) {
			mp = placemap.get(xy);
			if(mp.day != this.day && this.day!=15)
				continue;
			
			if(!filterText.isEmpty()  )
			{
				boolean cont = false;
				for(Integer index : mp.category)
				{
				 cont |= filterText.contains(index);
				}
				if(!cont) continue;
			}
			x = mp.x;
			y= mp.y;
			size = (int)Math.log(mp.count*100)*this.ellipseSize;

			if(this.day!=15 && !filterText.isEmpty()){
				int anz= 0;
				for(Integer index : mp.category)
				{
				 anz += filterText.contains(index) ? 1 : 0;
				 
				}
				size = (int)Math.log( (mp.count - anz)*100)*this.ellipseSize > 5 ? (int)Math.log( (mp.count - anz)*100)*this.ellipseSize :this.ellipseSize ;
			}
			tonality = mp.tonality/mp.count;
			fill(this.col[2][0], this.col[2][1], this.col[2][2],90);
//			if(!this.interval)
//			{
//				if(this.upperTonality < tonality)
//					continue;
//			}else
//			{
//				if( tonality< this.upperTonality-2 || tonality > this.upperTonality+2   )
//					continue;
//			}
			if(tonality< -5)
			{
				fill(this.col[1][0], this.col[1][1], this.col[1][2],90);
				stroke(100);
			}else if(tonality<5) {
				fill(this.col[2][0], this.col[2][1], this.col[2][2],90);
				stroke(100);
			}else{
				fill(this.col[0][0], this.col[0][1], this.col[0][2],90);
				stroke(100);
			}
			ellipse(x, y, size, size);
			cnt++;
		}

	}

	private final void extract() throws Exception {
		XMLReader xr = XMLReaderFactory.createXMLReader();
		xr.setContentHandler(new GetLocations());
		xr.parse(result);
	}

//	void mouseWheel(final int delta) {
//	  if(zoom > 1 || delta > 0) zoom += delta; 
//	  wmap.drawBackground(zoom);
//	}

	private String query() {
		// InfoVis_SS09_examdata
//		String q = "  for $x in /DOCUMENT/HEADER "
//		+ "let $geo := $x/DOC_ATTRS/DOC_ATTR/georss[position()=1], "
//		+" $cat := $x/DOC_ATTRS/DOC_ATTR[@name=\"emm_categories\"]/category[last()]/text(),"
//		+" $tone := $x/DOC_ATTRS/DOC_ATTR[@name=\"emm_tonality\"]/@value"
//		+" where $geo and $cat and $tone "
//		+"  return  "
//		+"  <r><c>{$cat}</c> <t>{$tone}</t> <d>{$x//CREATION_DATE/@value}</d><g>{$geo/@longitude}{$geo/@latitude} </g> </r>";

//		bxc = new BaseXConnection("localhost", 1984,"open InfoVis_SS09_examdata");
//		bxc.getResult();
//		bxc = new BaseXConnection("localhost", 1984, q);
//		String res = bxc.getResult();
//		try {
//			FileWriter f = new FileWriter("../etc/test.xml");
//			f.flush();
//			f.append("<doc>" + res + "</doc>");
//			f.close();
//		} catch (Exception e) { }
		return "../etc/test.xml";
	}

	/**
	 * @param theEvent
	 * iterate through events
	 */
	void controlEvent(final ControlEvent theEvent) {
	  final int id = theEvent.controller().id();
	  switch(id) {
	  case 1:
	  	this.ellipseSize = (int)(theEvent.controller().value());
	  	break;
	  case 2:
	  break;
	  case 3:
	  	this.filter = "";
	  	drawNews();
	  break;
	  case 5:
	  	final int day = (int)(theEvent.controller().value());
	  	this.day = day;
	  	final String str = day < 15 ? "Day "+ GetLocations.daynames[day] : "All Days";
	  	guiControls.timeSlider.setLabel( str);

	  break;
	  case 1337:
	  	this.filter = guiControls.filterValue();
	  	guiControls.filterField.setLabel("Filter");

	  break;
	  }
	}
	
	class MapPoint{
		private int tonality,count,x,y, day;
		 ArrayList<Integer> category;
		
		public MapPoint(final int x, final int y,final int i)
		{
			this.x = x;
			this.y = y;
			this.tonality = GetLocations.tonality.get(i);
			this.category = new ArrayList<Integer>();
			this.category.add(GetLocations.getCatId(i));
			this.day = GetLocations.getDay(i);
			this.count = 1;
		}
		public final void add(final int id)
		{
			this.tonality += GetLocations.tonality.get(id);
			this.category.add(GetLocations.getCatId(id));
			this.count++;
		}
	}


}
